import os
import sys
import collections

ntDiskUsage = collections.namedtuple('usage', 'name path total used free')

if hasattr(os, 'statvfs'):  # POSIX
    def get_disk_space(ntdu):
        st = os.statvfs(ntdu.path)
        free = st.f_bavail * st.f_frsize
        total = st.f_blocks * st.f_frsize
        used = (st.f_blocks - st.f_bfree) * st.f_frsize
        return ntDiskUsage(ntdu.name, ntdu.path, total, used, free)
elif os.name == 'nt':       # Windows
    import ctypes
    def get_disk_space(ntdu):
        _, total, free = ctypes.c_ulonglong(), ctypes.c_ulonglong(), \
                           ctypes.c_ulonglong()
        if sys.version_info >= (3,) or isinstance(ntdu.path, bytes):  # isinstance(path, unicode):
            path = ntdu.path.decode('ascii')
            fun = ctypes.windll.kernel32.GetDiskFreeSpaceExW
        else:
            path = ntdu.path
            fun = ctypes.windll.kernel32.GetDiskFreeSpaceExA
        ret = fun(path, ctypes.byref(_), ctypes.byref(total), ctypes.byref(free))
        if ret == 0:
            raise ctypes.WinError()
        used = total.value - free.value
        return ntDiskUsage(ntdu.name, ntdu.path, total.value, used, free.value)
else:
    raise NotImplementedError("platform not supported")


def get_disk_usage(d):
    pass


def diskstats_parse(dev=None):
    file_path = '/proc/diskstats'
    result = {}

    # ref: http://lxr.osuosl.org/source/Documentation/iostats.txt
    columns_disk = ['m', 'mm', 'dev', 'reads', 'rd_mrg', 'rd_sectors',
                    'ms_reading', 'writes', 'wr_mrg', 'wr_sectors',
                    'ms_writing', 'cur_ios', 'ms_doing_io', 'ms_weighted']

    columns_partition = ['m', 'mm', 'dev', 'reads', 'rd_sectors', 'writes', 'wr_sectors']

    lines = open(file_path, 'r').readlines()
    for line in lines:
        if line == '': continue
        split = line.split()
        if len(split) == len(columns_disk):
            columns = columns_disk
        elif len(split) == len(columns_partition):
            columns = columns_partition
        else:
            # No match
            continue

        data = dict(zip(columns, split))
        if dev is not None and dev != data['dev']:
            continue
        for key in data:
            if key != 'dev':
                data[key] = int(data[key])
        result[data['dev']] = data

    return result


def get_partitions(dev=None):
    file_path = '/proc/partitions'
    columns = ['ma', 'mi', 'blocks', 'dev']
    result = {}
    lines = open(file_path, 'r').readlines()
    for line in lines:
        if line == '': continue
        split = line.split()
        if len(split) != len(columns): continue
        data = dict(zip(columns, split))
        if dev is not None and dev != data['dev']:
            continue
        for key in data:
            if key != 'dev':
                data[key] = int(data[key])
        result[data['dev']] = data

    return result